<script setup lang="ts">
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { ElInput, ElButton, ElScrollbar, ElAvatar, ElDivider } from 'element-plus'
import { sendMessageToDify, DifyRequest, DifyConfig, DifyStreamingResponse } from '@/api/dify'

const props = defineProps({
  apiKey: {
    type: String,
    required: true
  },
  apiBase: {
    type: String,
    default: 'https://api.dify.ai/v1'
  },
  title: {
    type: String,
    default: '智能助手'
  },
  placeholder: {
    type: String,
    default: '请输入您的问题...'
  },
  inputs: {
    type: Object,
    default: () => ({})
  }
})

// 聊天消息类型
interface ChatMessage {
  id: string
  content: string
  role: 'user' | 'assistant'
  loading?: boolean
  createdAt: Date
  lastText?: string
}

// 聊天状态
const chatState = reactive({
  messages: [] as ChatMessage[],
  currentInput: '',
  loading: false,
  conversationId: ''
})

// 滚动区域引用
const chatScrollRef = ref<InstanceType<typeof ElScrollbar> | null>(null)

// 消息输入框引用
const inputRef = ref<InstanceType<typeof ElInput> | null>(null)

// 定义要向父组件传递的事件
const emit = defineEmits(['message-end', 'json-extracted', 'onFinish'])

// 自动滚动到底部
const scrollToBottom = () => {
  setTimeout(() => {
    try {
      // 使用更可靠的方式滚动
      const container = document.querySelector('.dify-chat .el-scrollbar__wrap')
      if (container) {
        container.scrollTop = container.scrollHeight
      }
    } catch (e) {
      console.error('滚动失败:', e)
    }
  }, 50)
}

// 添加消息
const addMessage = (content: string, role: 'user' | 'assistant', loading = false) => {
  const message: ChatMessage = {
    id: Date.now().toString() + Math.random().toString(36).substring(2, 9),
    content,
    role,
    loading,
    createdAt: new Date(),
    lastText: ''
  }
  chatState.messages.push(message)
  scrollToBottom()
  return message
}

// 格式化消息内容（支持换行和高亮代码）
const formatMessage = (message: string) => {
  if (!message) return ''

  // 替换换行符为<br>
  let formatted = message.replace(/\n/g, '<br />')

  // 处理代码块
  formatted = formatted.replace(/```([\s\S]*?)```/g, (match, code) => {
    return `<div class="code-block"><pre>${code}</pre></div>`
  })

  return formatted
}

// 发送消息
const sendMessage = async () => {
  if (!chatState.currentInput.trim() || chatState.loading) return

  const userMessage = chatState.currentInput.trim()
  addMessage(userMessage, 'user')

  // 清空输入框并聚焦
  chatState.currentInput = ''
  setTimeout(() => inputRef.value?.focus(), 100)

  // 新增 lastText 字段
  const assistantMessage = addMessage('', 'assistant', true)
  assistantMessage.lastText = ''

  chatState.loading = true

  try {
    const config: DifyConfig = {
      apiKey: props.apiKey,
      apiBase: props.apiBase
    }

    // 确保inputs是有效的对象
    const inputs = typeof props.inputs === 'object' && props.inputs !== null ? props.inputs : {}

    const request: DifyRequest = {
      query: userMessage,
      response_mode: 'streaming',
      user: 'user-20250515',
      inputs: inputs
    }

    if (chatState.conversationId) {
      request.conversation_id = chatState.conversationId
    }

    // 请求日志，便于调试
    console.log(
      '发送请求到Dify:',
      JSON.stringify({
        query: request.query,
        inputs_summary: Object.keys(inputs || {}),
        conversation_id: request.conversation_id
      })
    )

    await sendMessageToDify(
      request,
      config,
      (text, event) => {
        assistantMessage.loading = false
        chatState.loading = false
        // 直接更新消息内容，确保实时显示
        assistantMessage.content += text
        assistantMessage.lastText = text
        // 强制更新视图
        chatState.messages = [...chatState.messages]

        scrollToBottom()
      },
      (response) => {
        if (response && response.conversation_id && !chatState.conversationId) {
          chatState.conversationId = response.conversation_id
        }
        console.log('response==========》', response)

        // 处理消息内容，移除<think>标签内容并提取JSON
        const processedContent = extractContentAndJson(assistantMessage.content)
        assistantMessage.content = processedContent.content

        // 如果有JSON数据，向父组件发送事件
        if (processedContent.jsonData) {
          console.log('提取到的JSON数据:', processedContent.jsonData)
          emit('json-extracted', processedContent.jsonData)
        }

        assistantMessage.loading = false
        chatState.loading = false

        // 向父组件发送会话结束事件和完整响应
        const result = {
          message: assistantMessage.content,
          response: response,
          extractedJson: processedContent.jsonData
        }

        emit('message-end', result)

        // 同时触发 onFinish 事件以兼容之前的代码
        console.log('回答完成')
        emit('onFinish', result)
      },
      (error) => {
        assistantMessage.content = '抱歉，消息发送失败，请重试。' + (error.message || '')
        assistantMessage.loading = false
        chatState.loading = false
      }
    )
  } catch (error) {
    assistantMessage.content = '抱歉，消息发送失败，请重试。'
    assistantMessage.loading = false
    chatState.loading = false
  }
}

// 监听Enter键发送消息
const handleKeyDown = (e: KeyboardEvent) => {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault()
    sendMessage()
  }
}

// 初始聊天
onMounted(() => {
  // 添加欢迎消息
  addMessage('你好！我是AI助手，有什么可以帮助您的？', 'assistant')
  // 设置输入框焦点
  inputRef.value?.focus()
})

// 监听消息变化自动滚动
watch(
  () => chatState.messages,
  () => scrollToBottom(),
  { deep: true }
)

// 处理消息内容，移除<think>标签并提取JSON
const extractContentAndJson = (text: string) => {
  const result = {
    content: text,
    jsonData: null as any
  }

  // 移除<think>标签内容
  result.content = text.replace(/<think>([\s\S]*?)<\/think>/g, '')

  // 尝试提取JSON格式内容
  const jsonRegex = /```json\s*([\s\S]*?)\s*```/g
  const jsonMatches = [...result.content.matchAll(jsonRegex)]

  if (jsonMatches.length > 0) {
    try {
      console.log('找到JSON块数量:', jsonMatches.length)

      // 尝试合并多个JSON对象到一个数组
      if (jsonMatches.length > 1) {
        const jsonArray: any[] = []
        for (const match of jsonMatches) {
          try {
            const jsonText = match[1].trim()
            const jsonObj = JSON.parse(jsonText)
            jsonArray.push(jsonObj)
          } catch (err) {
            console.error('解析单个JSON块失败:', err)
          }
        }
        if (jsonArray.length > 0) {
          result.jsonData = jsonArray
        }
      } else {
        // 只有一个JSON块的情况
        const jsonText = jsonMatches[0][1].trim()
        result.jsonData = JSON.parse(jsonText)
      }

      // 可选：从原文本中移除JSON代码块
      // result.content = result.content.replace(/```json\s*([\s\S]*?)\s*```/g, '')
    } catch (error) {
      console.error('解析JSON失败:', error)
    }
  }

  // 清理多余的空行
  result.content = result.content.replace(/\n{3,}/g, '\n\n').trim()

  return result
}
</script>

<template>
  <div class="dify-chat">
    <!-- 聊天区域 -->
    <div class="chat-container">
      <ElScrollbar ref="chatScrollRef" class="chat-messages">
        <div class="message-list">
          <div
            v-for="message in chatState.messages"
            :key="message.id"
            :class="['message', `message-${message.role}`]"
          >
            <div class="message-avatar">
              <ElAvatar
                :size="40"
                :src="message.role === 'assistant' ? '' : ''"
                :icon="message.role === 'assistant' ? 'ChatDotRound' : 'User'"
              />
            </div>
            <div class="message-content">
              <div class="message-text" v-html="formatMessage(message.content)"></div>
              <div v-if="message.loading" class="message-loading">
                <span class="dot-1"></span>
                <span class="dot-2"></span>
                <span class="dot-3"></span>
              </div>
            </div>
          </div>
        </div>
      </ElScrollbar>
    </div>

    <!-- 输入区域 -->
    <div class="chat-input-container">
      <ElDivider />
      <div class="chat-input">
        <ElInput
          ref="inputRef"
          v-model="chatState.currentInput"
          :placeholder="placeholder"
          type="textarea"
          :rows="3"
          resize="none"
          @keydown="handleKeyDown"
        />
        <ElButton type="primary" @click="sendMessage"> 发送 </ElButton>
      </div>
    </div>
  </div>
</template>

<style lang="less" scoped>
.dify-chat {
  display: flex;
  flex-direction: column;
  height: 100%;
  background-color: #f9f9f9;
  border-radius: 8px;
  overflow: hidden;
}

.chat-container {
  flex: 1;
  overflow: hidden;
  padding: 16px;
}

.chat-messages {
  height: 100%;
}

.message-list {
  padding: 10px 0;
}

.message {
  display: flex;
  margin-bottom: 20px;

  &.message-user {
    flex-direction: row-reverse;

    .message-content {
      background-color: #e7f2ff;
      border-radius: 10px 2px 10px 10px;
      margin-right: 10px;
    }
  }

  &.message-assistant .message-content {
    background-color: #fff;
    border-radius: 2px 10px 10px 10px;
    margin-left: 10px;
  }
}

.message-avatar {
  flex-shrink: 0;
}

.message-content {
  padding: 12px 16px;
  max-width: 80%;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);

  :deep(.code-block) {
    margin: 10px 0;
    background-color: #f5f5f5;
    border-radius: 4px;
    overflow: auto;

    pre {
      padding: 12px;
      margin: 0;
      font-family: 'Courier New', Courier, monospace;
      white-space: pre-wrap;
      word-break: break-all;
    }
  }
}

.message-text {
  word-break: break-word;
  white-space: pre-wrap;
  line-height: 1.5;
}

.message-loading {
  margin-top: 8px;
  display: flex;

  .dot-1,
  .dot-2,
  .dot-3 {
    width: 8px;
    height: 8px;
    background: #ccc;
    border-radius: 50%;
    margin-right: 5px;
    animation: dot-bounce 1.4s infinite ease-in-out both;
  }

  .dot-1 {
    animation-delay: -0.32s;
  }

  .dot-2 {
    animation-delay: -0.16s;
  }
}

@keyframes dot-bounce {
  0%,
  80%,
  100% {
    transform: scale(0);
  }
  40% {
    transform: scale(1);
  }
}

.chat-input-container {
  padding: 0 16px 16px;
}

.chat-input {
  display: flex;
  align-items: flex-end;

  .el-input {
    flex: 1;
    margin-right: 10px;
  }

  .el-button {
    height: 40px;
  }
}
</style>
